package xiao_jin.fantastic_journey.generator;

import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider;
import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.condition.MatchToolLootCondition;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.entry.LeafEntry;
import net.minecraft.loot.entry.LootPoolEntry;
import net.minecraft.loot.function.ApplyBonusLootFunction;
import net.minecraft.loot.function.SetCountLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
import net.minecraft.predicate.item.ItemPredicate;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.ItemTags;
import xiao_jin.fantastic_journey.core.init.ModBlocks;
import xiao_jin.fantastic_journey.core.init.ModItems;

import java.util.concurrent.CompletableFuture;

@SuppressWarnings({"unused", "unchecked", "all"})
public final class ModLootTablesProvider extends FabricBlockLootTableProvider {
    public ModLootTablesProvider(FabricDataOutput dataOutput, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) {
        super(dataOutput, registryLookup);
    }

    /**
     * 锹类工具规则变量
     */
    public static final LootCondition.Builder SHOVEL = MatchToolLootCondition
            .builder(ItemPredicate.Builder
                    .create()
                    .tag(ItemTags.SHOVELS));

    @Override
    public void generate() {
        addDrop(ModBlocks.RELICTECH_TABLE);
        addDrop(ModBlocks.RELICTECH_QUARTET_LOCK);
        addDrop(ModBlocks.RELICTECH_BASE_STONE);
        addDrop(ModBlocks.RELICTECH_STONE);
        addDrop(ModBlocks.RELICTECH_STONE_SLAB);
        addDrop(ModBlocks.RELICTECH_STONE_STAIRS);
        addDrop(ModBlocks.RELICTECH_STONE_WALL);
        addDrop(ModBlocks.RELICTECH_STONE_BRICKS);
        addDrop(ModBlocks.RELICTECH_STONE_BRICKS_SLAB);
        addDrop(ModBlocks.RELICTECH_STONE_BRICKS_STAIRS);
        addDrop(ModBlocks.RELICTECH_STONE_BRICKS_WALL);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_SLAB);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_STAIRS);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_WALL);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_BRICKS);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_BRICKS_SLAB);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_BRICKS_STAIRS);
        addDrop(ModBlocks.RELICTECH_CRACK_STONE_BRICKS_WALL);
        addDrop(ModBlocks.DEEP_RELICTECH_STONE);
        addDrop(ModBlocks.DEEP_RELICTECH_STONE_SLAB);
        addDrop(ModBlocks.DEEP_RELICTECH_STONE_STAIRS);
        addDrop(ModBlocks.DEEP_RELICTECH_STONE_WALL);

        addDrop(ModBlocks.EXPLOSIVE_STEEL_BLOCK);
        addDrop(ModBlocks.CULTIVATED_WASTE_SOIL, of().pool(shovel(ModBlocks.WASTE_SOIL)));
        addDrop(ModBlocks.SILICIFIED_WASTE_SOIL, (dropsWithSilkTouch(ModBlocks.SILICIFIED_WASTE_SOIL).pool(shovel(ModBlocks.WASTE_SOIL))));
        addDrop(ModBlocks.WASTE_SOIL, of().pool(shovel(ModBlocks.WASTE_SOIL)));

        addDrop(net.minecraft.block.Blocks.IRON_BLOCK, explosionDrops(ModItems.EXPLOSIVE_STEEL_PIECE, 0.0f, 5.0f));

        //矿石
        addDrop(ModBlocks.RELICTECH_COPPER_ORE, MostDroppedObjectsOreDrops(ModBlocks.RELICTECH_COPPER_ORE, Items.RAW_COPPER, 2.0f, 5.0f));
        addDrop(ModBlocks.DEEP_RELICTECH_COPPER_ORE, MostDroppedObjectsOreDrops(ModBlocks.DEEP_RELICTECH_COPPER_ORE, Items.RAW_COPPER, 2.0f, 5.0f));
        addDrop(ModBlocks.RELICTECH_EMERALD_ORE, oreDrops(ModBlocks.RELICTECH_EMERALD_ORE, Items.EMERALD));
        addDrop(ModBlocks.DEEP_RELICTECH_EMERALD_ORE, oreDrops(ModBlocks.DEEP_RELICTECH_EMERALD_ORE, Items.EMERALD));
        addDrop(ModBlocks.RELICTECH_GOLD_ORE, oreDrops(ModBlocks.RELICTECH_GOLD_ORE, Items.RAW_GOLD));
        addDrop(ModBlocks.DEEP_RELICTECH_GOLD_ORE, oreDrops(ModBlocks.DEEP_RELICTECH_GOLD_ORE, Items.RAW_GOLD));
        addDrop(ModBlocks.RELICTECH_IRON_ORE, oreDrops(ModBlocks.RELICTECH_IRON_ORE, Items.RAW_IRON));
        addDrop(ModBlocks.DEEP_RELICTECH_IRON_ORE, oreDrops(ModBlocks.DEEP_RELICTECH_IRON_ORE, Items.RAW_IRON));
        addDrop(ModBlocks.RELICTECH_LAPIS_ORE, MostDroppedObjectsOreDrops(ModBlocks.RELICTECH_LAPIS_ORE, Items.LAPIS_LAZULI, 4.0f, 9.0f));
        addDrop(ModBlocks.DEEP_RELICTECH_LAPIS_ORE, MostDroppedObjectsOreDrops(ModBlocks.DEEP_RELICTECH_LAPIS_ORE, Items.LAPIS_LAZULI, 4.0f, 9.0f));
        addDrop(ModBlocks.RELICTECH_REDSTONE_ORE, redstoneOreDrops(ModBlocks.RELICTECH_REDSTONE_ORE, Items.REDSTONE, 4.0f, 5.0f));
        addDrop(ModBlocks.DEEP_RELICTECH_REDSTONE_ORE, redstoneOreDrops(ModBlocks.DEEP_RELICTECH_REDSTONE_ORE, Items.REDSTONE, 4.0f, 5.0f));
        addDrop(ModBlocks.RELICTECH_DIAMOND_ORE, oreDrops(ModBlocks.RELICTECH_DIAMOND_ORE, Items.DIAMOND));
        addDrop(ModBlocks.DEEP_RELICTECH_DIAMOND_ORE, oreDrops(ModBlocks.RELICTECH_DIAMOND_ORE, Items.DIAMOND));

    }

    public static LootTable.Builder of() {
        return new LootTable.Builder();
    }

    /**
     * 爆炸摧毁掉落
     *
     * @param item 掉落物
     * @param min  最小掉落数量
     * @param max  最大掉落数量
     */
    public static LootTable.Builder explosionDrops(ItemConvertible item, float min, float max) {
        return LootTable
                .builder()
                .pool(LootPool.builder()
                        .rolls(UniformLootNumberProvider.create(min, max))
                        .with(ItemEntry.builder(item)));
    }

    /**
     * 锹类工具掉落
     */
    public static LootPool.Builder shovel(Block item) {
        return LootPool
                .builder()
                .conditionally(SHOVEL).
                rolls(ConstantLootNumberProvider.create(1.0f))
                .with(ItemEntry.builder(item));
    }

    /**
     * 多数量掉落物矿石掉落规则 《铜矿&青金石矿类》
     *
     * @param block 精准采集掉落物
     * @param item  掉落物
     * @param min   最小掉落数量
     * @param max   最大掉落数量
     */
    public LootTable.Builder MostDroppedObjectsOreDrops(Block block, Item item, float min, float max) {
        return this.dropsWithSilkTouch(block, (LootPoolEntry.Builder) this.applyExplosionDecay(block, ((LeafEntry.Builder) ItemEntry
                .builder(item)
                .apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(min, max))))
                .apply(ApplyBonusLootFunction.oreDrops(getEnchantment(Enchantments.FORTUNE)))));
    }

    /**
     * 多数量掉落物矿石掉落规则 《红石矿类》
     *
     * @param block 精准采集掉落物
     * @param item  掉落物
     * @param min   最小掉落数量
     * @param max   最大掉落数量
     */
    public LootTable.Builder redstoneOreDrops(Block block, Item item, float min, float max) {
        return this.dropsWithSilkTouch(block, (LootPoolEntry.Builder) this.applyExplosionDecay(block, ((LeafEntry.Builder) ItemEntry
                .builder(item)
                .apply(SetCountLootFunction.builder(UniformLootNumberProvider.create(min, max))))
                .apply(ApplyBonusLootFunction.uniformBonusCount(getEnchantment(Enchantments.FORTUNE)))));
    }

    protected final RegistryEntry<Enchantment> getEnchantment(RegistryKey<Enchantment> key) {
        return registryLookup.getWrapperOrThrow(RegistryKeys.ENCHANTMENT).getOrThrow(key);
    }
}
